#include "AC33Mxxx_conf.h"


CSP_SCS_T		* const		SCS 		= (CSP_SCS_T *) SCS_BASE_ADDRESS;
CSP_SYSTICK_T 	* const		SYSTICK		= (CSP_SYSTICK_T *) SYSTICK_BASE_ADDRESS; 
CSP_NVIC_T		* const		NVIC		= (CSP_NVIC_T *) NVIC_BASE_ADDRESS; 
CSP_SCB_T		* const		SCB 		= (CSP_SCB_T *) SCB_BASE_ADDRESS;

CSP_TPIU_T		* const		TPIU		= (CSP_TPIU_T *) TPIU_BASE_ADDRESS; 

/**
************************************************************************************
* @ Name : CSP_SysTick_Init
*
* @ Parameter
*		- systick		= SYSTICK 
*		- clk_src		= ST_CORE_CLOCK, ST_EXTREF_CLOCK
*		- ext_ref		= 0 (core clock), 
*		- ext_div		= 0 (core clock), 
*		- reload 
*
*
*
************************************************************************************
*/
void CSP_SysTick_Init (CSP_SYSTICK_T * const systick, UINT32 clk_src, UINT32 ext_ref, UINT32 ext_div, UINT32 reload)
{

	if (clk_src == ST_CORE_CLOCK)
	{
		CSP_SYSTICK_SET_CSR(systick, (CSP_SYSTICK_GET_CSR(systick) & ~CSR_CLKSOURCE)); 
		CSP_SYSTICK_SET_CSR(systick, (CSP_SYSTICK_GET_CSR(systick) | CSR_CLKSOURCE_CORE_CLOCK)); 
	}
	else if (clk_src == ST_EXTREF_CLOCK)
	{
		CSP_SYSTICK_SET_CSR(systick, (CSP_SYSTICK_GET_CSR(systick) & ~CSR_CLKSOURCE)); 
		CSP_SYSTICK_SET_CSR(systick, (CSP_SYSTICK_GET_CSR(systick) | CSR_CLKSOURCE_EXTREF_CLOCK)); 

	}
	else 
		return; 



	//------------------------------------------------------------------------------
	// reload 
	//------------------------------------------------------------------------------
	CSP_SYSTICK_SET_RVR(systick, reload); 



	//------------------------------------------------------------------------------
	// clear current value 
	//------------------------------------------------------------------------------
	CSP_SYSTICK_SET_CVR(systick, 0); 


}



/**
************************************************************************************
* @ Name : CSP_SysTick_ConfigureInterrupt
*
* @ Parameter
*		- systick		= SYSTICK 
*
*
*
************************************************************************************
*/
void CSP_SysTick_Run (CSP_SYSTICK_T * const systick)
{

	CSP_SYSTICK_SET_CSR(systick, (CSP_SYSTICK_GET_CSR(systick) | CSR_ENABLE)); 
}




/**
************************************************************************************
* @ Name : CSP_SysTick_ConfigureInterrupt
*
* @ Parameter
*		- systick		= SYSTICK 
*		- intr_mask	= ST_INTR_TICK
*		- enable		= SYSINT_ENABLE, SYSINT_DISABLE 
*
*
*
************************************************************************************
*/
void CSP_SysTick_ConfigureInterrupt (CSP_SYSTICK_T * const systick, UINT32 intr_mask, UINT32 enable)
{
	volatile UINT32		reg_val; 

	
	//------------------------------------------------------------------------------
	// disable interrupt 
	//------------------------------------------------------------------------------
	CSP_SYSTICK_SET_CSR(systick, (CSP_SYSTICK_GET_CSR(systick) & ~CSR_TICKINT)); 
	

	//------------------------------------------------------------------------------
	// clear interrupt flag 
	//------------------------------------------------------------------------------
	CSP_SCB_SET_ICSR(SCB, ICSR_PENDSTCLR);
	reg_val = CSP_SYSTICK_GET_CSR(systick); 


	//------------------------------------------------------------------------------
	// enable interrupt 
	//------------------------------------------------------------------------------
	if (enable == SYSINT_ENABLE)
	{
		CSP_SYSTICK_SET_CSR(systick, (CSP_SYSTICK_GET_CSR(systick) | CSR_TICKINT)); 
	}

}




/**
***********************************************************************************************************
* @ Name : CSP_SCB_Set_PriorityGroup
*
* @ Parameters
*		scb				SCB
*		priority_group		PRIORITY_GROUP_VALUE
*
* @ Register 
*		- AIRCR : PRIGROUP [10:8]    		(0xE000_ED0C)
*
*			bit 31-16		VECTKEY
*			bit 15		ENDIANESS
*			bit 10-8		PRIGROUP
*
*			bit 2			SYSRESETREQ
*			bit 1			VECTCLRACTIVE
*			bit 0			VECTRESET
*
*
***********************************************************************************************************
* Priority Group
*
*			0 	preemption priority field[7:1]		subpriority field[0]
*			1 	preemption priority field[7:2]		subpriority field[1:0]
*			2 	preemption priority field[7:3]		subpriority field[2:0]
*			3 	preemption priority field[7:4]		subpriority field[3:0]
*			4 	preemption priority field[7:5]		subpriority field[4:0]
*			5 	preemption priority field[7:6]		subpriority field[5:0]
*			6 	preemption priority field[7]		subpriority field[6:0]
*			7 	preemption priority field=none	subpriority field[7:0]
*
*			(referenced at page 114 in "The Definitive Guide to ARM Cortex-M3")
*
************************************************************************************************************
*/
void CSP_SCB_Set_PriorityGroup (CSP_SCB_T * const scb, UINT32 priority_group)
{
	UINT32		reg_val;

	reg_val = CSP_SCB_GET_AIRCR(scb); 
	
	reg_val &= ~(AIRCR_VECTKEY_MASK|AIRCR_PRIGROUP_MASK); 
	reg_val |= ((priority_group<<8) & AIRCR_PRIGROUP_MASK); 
	reg_val |= AIRCR_VECTKEY; 

	
	CSP_SCB_SET_AIRCR(scb, reg_val); 

}


/**
***********************************************************************************************************
* @ Name : CSP_SCB_ConfigureException
*
* @ Parameters
*		scb									SCB
*		exception_config->nException_Number	= SYS_EXCEPT_MEMORY_MANAGE (-4)
*											   SYS_EXCEPT_BUS_FAULT (-5)
*											   SYS_EXCEPT_USAGE_FAULT (-6)
*											   SYS_EXCEPT_SYSTICK (-15)
*
*		exception_config->u8Preemption_Priority	= 0~1
*		exception_config->u8Subpriority			= 0~3
*		exception_config->u8ExceptionEnable		= EXCEPTION_ENABLE, EXCEPTION_DISABLE
*
* @ Registers
*
*
* @ Descriptions
*		This function is used for system exceptions. 
*
************************************************************************************************************
*/
#if 0
void CSP_SCB_ConfigureException (CSP_SCB_T * const scb, SCB_ExceptionConfig * exception_config)
{
	int					vector_num; 
	UINT32				group, remnant, shift; 
	
	UINT32				priority, bit_val,bit_mask; 
	
	//int					exception_num; 
	//UINT32				exception_group; 
	//UINT32				exception_bitpos;

	volatile UINT32		reg_val; 


	//--------------------------------------------------------------------------------------
	// check "interrupt number" 
	//--------------------------------------------------------------------------------------
	if ((exception_config->nException_Number < -15) || (exception_config->nException_Number > -4)) return; 


	//--------------------------------------------------------------------------------------
	// exception number (negative) --> vector number (positive)
	//--------------------------------------------------------------------------------------
	vector_num = -(exception_config->nException_Number); 


	//--------------------------------------------------------------------------------------
	// disable exception
	//--------------------------------------------------------------------------------------
	switch (vector_num)
	{
	case VECT_NUM_MEMORY_MANAGE:
		CSP_SCB_SET_SHCSR(SCB, (CSP_SCB_GET_SHCSR(SCB) & ~SHCSR_MEMFAULTENA));
		break;

	case VECT_NUM_BUS_FAULT:
		CSP_SCB_SET_SHCSR(SCB, (CSP_SCB_GET_SHCSR(SCB) & ~SHCSR_BUSFAULTENA));
		break; 

	case VECT_NUM_USAGE_FAULT:
		CSP_SCB_SET_SHCSR(SCB, (CSP_SCB_GET_SHCSR(SCB) & ~SHCSR_USGFAULTENA));
		break; 

	case VECT_NUM_SYSTICK:
		CSP_SYSTICK_SET_CSR(SYSTICK, (CSP_SYSTICK_GET_CSR(SYSTICK) & ~CSR_TICKINT)); 
		break; 

	default:
		break; 
	}
	


	//--------------------------------------------------------------------------------------
	// clear pending bit 
	//--------------------------------------------------------------------------------------
	switch (vector_num)
	{
	case VECT_NUM_MEMORY_MANAGE:
		CSP_SCB_SET_CFSR(SCB, 0x000000FF); 
		break;

	case VECT_NUM_BUS_FAULT:
		CSP_SCB_SET_CFSR(SCB, 0x0000FF00); 
		break; 

	case VECT_NUM_USAGE_FAULT:
		CSP_SCB_SET_CFSR(SCB, 0xFFFF0000UL); 
		break; 

	case VECT_NUM_SYSTICK:
		reg_val = CSP_SYSTICK_GET_CSR(SYSTICK); 		// clear CSR:COUNTFLAG
		CSP_SCB_SET_ICSR(SCB, ICSR_PENDSTCLR); 
		break; 

	default:
		break; 
	} 


	//--------------------------------------------------------------------------------------
	// filtering
	//--------------------------------------------------------------------------------------
	if (exception_config->u8ExceptionEnable == EXCEPTION_DISABLE) return; 
	

	//--------------------------------------------------------------------------------------
	// set priority 
	//
	//				vector_num		group 		remnant		shfit
	//				----------		-----		-------		-----
	//				4				0			0			0
	//				5				0			1			8
	//				6				0			2			16
	//				7				0			3			24	
	//
	//				8				1			0			0
	//				9				1			1			8
	//				10				1			2			16
	//				11				1			3			24		
	//
	//				12				2			0			0
	//				13				2			1			8
	//				14				2			2			16
	//				15				2			3			24	
	//
	//--------------------------------------------------------------------------------------
	// bit operations 
	group = ((vector_num - 4) >> 2);
	remnant = ((vector_num - 4) & 0x03); 
	shift = (remnant << 3); 
	
	priority = (exception_config->u8Subpriority << START_BITPOS_OF_PRIORITY) & SUBPRIORITY_MASK;
	priority |= (exception_config->u8Preemption_Priority << (PRIORITY_GROUP_VALUE+1)) & PREEMPTION_MASK; 

	bit_val = (priority << shift); 
	bit_mask = (0xFFUL << shift); 


	// action 
	CSP_SCB_SET_SHPR(SCB, group, ((CSP_SCB_GET_SHPR(SCB, group) & ~bit_mask) | bit_val)); 


	//--------------------------------------------------------------------------------------
	// enable interrupt 
	//--------------------------------------------------------------------------------------
	switch (vector_num)
	{
	case VECT_NUM_MEMORY_MANAGE:
		CSP_SCB_SET_SHCSR(SCB, (CSP_SCB_GET_SHCSR(SCB) | SHCSR_MEMFAULTENA));
		break;

	case VECT_NUM_BUS_FAULT:
		CSP_SCB_SET_SHCSR(SCB, (CSP_SCB_GET_SHCSR(SCB) | SHCSR_BUSFAULTENA));
		break; 

	case VECT_NUM_USAGE_FAULT:
		CSP_SCB_SET_SHCSR(SCB, (CSP_SCB_GET_SHCSR(SCB) | SHCSR_USGFAULTENA));
		break; 

	case VECT_NUM_SYSTICK:
		CSP_SYSTICK_SET_CSR(SYSTICK, (CSP_SYSTICK_GET_CSR(SYSTICK) | CSR_TICKINT)); 
		break; 

	default:
		break; 
	}

}
#endif 


/**
***********************************************************************************************************
* @ Name : CSP_NVIC_ConfigureInterrupt
*
* @ Parameters
*		nvic								NVIC
*		nvic_config->nIRQ_Number			= 0~31
*		nvic_config->u8Preemption_Priority	= 0~1
*		nvic_config->u8Subpriority			= 0~3
*		nvic_config->u8IntrEnable			= INTR_ENABLE, INTR_DISABLE
*
* @ Registers
*		ICER
*		IPR
*		ISER
*
* @ Descriptions
*		This function is used for IRQ (Vector number = 16 ~ )
*
************************************************************************************************************
*/
void CSP_NVIC_ConfigureInterrupt (CSP_NVIC_T * const nvic, NVIC_IntrConfig * nvic_config)
{
	UINT8			priority;
	int				irq_num;
	UINT8			irq_group; 
	UINT32			irq_bitpos; 


	//--------------------------------------------------------------------------------------
	// check "interrupt number" 
	//--------------------------------------------------------------------------------------
	if ((nvic_config->nIRQ_Number < 0) || (nvic_config->nIRQ_Number >= AC33M8128_IRQ_NUM)) return; 


	//--------------------------------------------------------------------------------------
	// bit operations 
	//--------------------------------------------------------------------------------------
	priority = (nvic_config->u8Subpriority << START_BITPOS_OF_PRIORITY) & SUBPRIORITY_MASK;
	priority |= (nvic_config->u8Preemption_Priority << (PRIORITY_GROUP_VALUE+1)) & PREEMPTION_MASK; 

	irq_num = nvic_config->nIRQ_Number;
	irq_group = (UINT8) (nvic_config->nIRQ_Number >> 5); 
	irq_bitpos = (0x0001UL << (nvic_config->nIRQ_Number & 0x1F)); 



	//--------------------------------------------------------------------------------------
	// disable interrupt
	//--------------------------------------------------------------------------------------
	CSP_NVIC_SET_ICER(nvic, irq_group, irq_bitpos); 


	//--------------------------------------------------------------------------------------
	// clear pending bit 
	//--------------------------------------------------------------------------------------
	CSP_NVIC_SET_ICPR (nvic, irq_group, irq_bitpos); 


	//--------------------------------------------------------------------------------------
	// filtering
	//--------------------------------------------------------------------------------------
	if (nvic_config->u8IntrEnable == INTR_DISABLE) return; 
	

	//--------------------------------------------------------------------------------------
	// set priority 
	//--------------------------------------------------------------------------------------
	CSP_NVIC_SET_IPR(nvic, irq_num, priority); 


	//--------------------------------------------------------------------------------------
	// enable interrupt 
	//--------------------------------------------------------------------------------------
	CSP_NVIC_SET_ISER(nvic, irq_group, irq_bitpos); 

}


